vue3
<!-- author: xuett -->
<!-- date: 2025-07-07 16:06:18 -->
<!-- description:  -->
<template>
  <div class="chart-box">
    <v-chart ref="chart3" :option="chartOption" autoresize @mouseover="chart3Mouseover" @mouseout="chart3Mouseout" />
  </div>
</template>

<script setup>
import * as echarts from "echarts";

const state = reactive({
  card3Data: [
    { name: "太原市", value1: 56, value2: 13, value3: 13, value4: 2, value5: 33 },
    { name: "大同市", value1: 157, value2: 9, value3: 9, value4: 8, value5: 10 },
    { name: "朔州市", value1: 9, value2: 9, value3: 7, value4: 7, value5: 4 },
    { name: "忻州市", value1: 163, value2: 9, value3: 28, value4: 0, value5: 20 },
    { name: "吕梁市", value1: 107, value2: 9, value3: 10, value4: 5, value5: 9 },
    { name: "晋中市", value1: 186, value2: 12, value3: 17, value4: 11, value5: 35 },
    { name: "阳泉市", value1: 78, value2: 6, value3: 7, value4: 5, value5: 15 },
    { name: "长治市", value1: 83, value2: 2, value3: 1, value4: 1, value5: 16 },
    { name: "晋城市", value1: 110, value2: 8, value3: 11, value4: 6, value5: 25 },
    { name: "临汾市", value1: 156, value2: 9, value3: 18, value4: 8, value5: 23 },
    { name: "运城市", value1: 155, value2: 13, value3: 23, value4: 10, value5: 23 }
  ],
  chartOption: {},
  chart3Select: {
    isSet: false,
    currentIndex: 0
  }
});
const { chartOption } = toRefs(state);

onMounted(() => {
  initChart();
});

//配套系统
const chart3 = ref();
const initChart = () => {
  let lineList = [
    {
      name: "慢行道(公里)",
      color: "rgba(89, 103, 189, 1)",
      prop: "value1"
    },
    {
      name: "观景台(个)",
      color: "rgba(136, 203, 122, 1)",
      prop: "value2"
    },
    {
      name: "营地(个)",
      color: "rgba(243, 197, 99, 1)",
      prop: "value3"
    },
    {
      name: "停车场(个)",
      color: "rgba(112, 185, 213, 1)",
      prop: "value4"
    },
    {
      name: "连接A级景区数(个)",
      color: "rgba(34, 108, 230, 1)",
      prop: "value5"
    }
  ];
  state.chartOption = {
    tooltip: {
      trigger: "axis",
      backgroundColor: "#255DA9",
      borderColor: "#255DA9",
      textStyle: {
        color: "#fff",
        fontSize: 14
      },
      axisPointer: {
        type: "shadow"
      }
    },
    grid: {
      top: "15%",
      right: "5%",
      left: "8%",
      bottom: "10%"
    },
    legend: {
      top: 10,
      left: "center",
      icon: "rect",
      itemGap: 40,
      itemWidth: 10,
      itemHeight: 10,
      data: lineList.map((item) => item.name),
      textStyle: {
        color: "#fff",
        fontSize: 18
      }
    },
    xAxis: {
      type: "category",
      // boundaryGap: false,
      axisLine: {
        lineStyle: {
          color: "rgba(178, 194, 211, 0.33)"
        }
      },
      axisTick: {
        show: false
      },
      axisLabel: {
        color: "#fff",
        fontSize: 18
      },
      splitLine: {
        show: true,
        lineStyle: {
          color: "rgba(60, 87, 135, 0.33)"
        }
      },
      data: state.card3Data.map((item) => item.name)
    },
    yAxis: {
      axisLabel: {
        color: "#FFFFFF",
        fontSize: 18
      },
      axisLine: {
        lineStyle: {
          color: "rgba(60, 87, 135, 0.33)"
        }
      },
      axisTick: {
        show: false
      },
      splitLine: {
        lineStyle: {
          type: "dashed",
          color: "rgba(178, 194, 211, 0.33)"
        }
      }
    },
    series: lineList.map((item) => {
      return {
        // name: i == 0 ? item.name + "公里" : item.name + "个",
        name: item.name,
        type: "bar",
        // lineStyle: {
        //   width: 2,
        //   color: item.color
        // },
        stack: "total",
        barWidth: 30,
        // symbol: "circle",
        // symbolSize: 8,
        areaStyle: {
          opacity: 0.2,
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            {
              offset: 0,
              color: item.color
            },
            {
              offset: 1,
              color: item.color
            }
          ])
        },
        data: state.card3Data.map((childItem) => childItem[item.prop])
      };
    })
  };
  if (chart3Timer) {
    clearInterval(chart3Timer);
    chart3Timer = null;
  }
  chart3Timer = setInterval(chart3Hover, 1500);
};
var chart3Timer = null;
const chart3Mouseover = (param) => {
  state.chart3Select.isSet = false;
  if (chart3Timer) {
    clearInterval(chart3Timer);
    chart3Timer = null;
  }
  // 取消之前高亮的图形
  chart3.value.dispatchAction({
    type: "downplay",
    seriesIndex: 0,
    dataIndex: state.chart3Select.currentIndex
  });
  // 高亮当前图形
  chart3.value.dispatchAction({
    type: "highlight",
    seriesIndex: 0,
    dataIndex: param.dataIndex
  });
  // 显示 tooltip
  chart3.value.dispatchAction({
    type: "showTip",
    seriesIndex: 0,
    dataIndex: param.dataIndex
  });
  state.chart3Select.currentIndex = param.dataIndex;
};

// 3、自动高亮展示
const chart3Hover = function () {
  if (!chart3.value) {
    return;
  }
  var dataLen = state.chartOption.series[0].data.length;
  // 取消之前高亮的图形
  chart3.value.dispatchAction({
    type: "downplay",
    seriesIndex: 0,
    dataIndex: state.chart3Select.currentIndex
  });
  state.chart3Select.currentIndex = (state.chart3Select.currentIndex + 1) % dataLen;
  // 高亮当前图形
  chart3.value.dispatchAction({
    type: "highlight",
    seriesIndex: 0,
    dataIndex: state.chart3Select.currentIndex
  });
  // 显示 tooltip
  chart3.value.dispatchAction({
    type: "showTip",
    seriesIndex: 0,
    dataIndex: state.chart3Select.currentIndex
  });
};
//鼠标移出之后，恢复自动高亮
const chart3Mouseout = () => {
  if (!state.chart3Select.isSet) {
    if (chart3Timer) {
      clearInterval(chart3Timer);
      chart3Timer = null;
    }
    chart3Timer = setInterval(chart3Hover, 2000);
    state.chart3Select.isSet = true;
  }
};
</script>

<style scoped lang="scss">
.chart-box {
  width: 100%;
  height: 100%;
  padding: 15px;
  background-color: #000;
}
</style>
